#include "GPUParamMap.h"

namespace egg{

    GPUParamMap::GPUParamMap(GPUProgramPtr _program){
        mProgram=_program;
    }

    GPUParamMap::~GPUParamMap(){
    }

    void GPUParamMap::bindParam(GPUParamPtr _param){
        ParamMap::iterator itr=mAllParams.find(_param->getName());
        if(itr==mAllParams.end()){
            mAllParams.insert(make_pair(_param->getName(),_param));
            addActiveParam(_param.get());
        }
    }

    void GPUParamMap::activate(){
        updateActiveParams();
        mProgram->activate();
        for(uint32 i=0;i<mTextures.size();i++){
            TextureParam* param=(TextureParam*)mTextures[i].second;
            uint32 slot=param->mTexture->activate();
            gDevice->commitParam(
                param->getType(),
                mTextures[i].first,
                &slot);
        }
        for(int i=0;i<mNumerics.size();i++){
            NumericParam* param=(NumericParam*)mNumerics[i].second;
            gDevice->commitParam(
                param->getType(),
                mNumerics[i].first,
                param->getData());
        }
    }

    NumericParamPtr GPUParamMap::getNumericParam(const string& _name){
        return getParam<NumericParam>(_name);
    }

    TextureParamPtr GPUParamMap::getTextureParam(const string& _name){
        return getParam<TextureParam>(_name);
    }

    //=======================================================================

    void GPUParamMap::updateActiveParams(){
        mProgram->update();
        if(mVersion!=mProgram->getVersion()){
            mVersion=mProgram->getVersion();
            mNumerics.clear();
            mTextures.clear();
            ParamMap::iterator itr=mAllParams.begin();
            for(;itr!=mAllParams.end();itr++){
                addActiveParam(itr->second.get());
            }
        }
    }

    void GPUParamMap::addActiveParam(GPUParam* _param){
        if(mProgram->checkParam(_param)){
            if(_param->getType()==GPT_Texture){
                mTextures.push_back(make_pair(
                    mProgram->_getParamLoc(_param->getName()),
                    _param));
            }else{
                mNumerics.push_back(make_pair(
                    mProgram->_getParamLoc(_param->getName()),
                    _param));
            }
        }
    }

}